package programming.in.scala

import java.io.{File, FileNotFoundException, FileReader, IOException}

import scala.collection.immutable.Seq._

/**
  * Created by baiwf on 2017/5/29.
  * 将imperative style转换成函数式
  */
class ch07_multiplication_table {
  def makeRowSeq(row: Int) = {
    for (col <- 1 to 10) yield {
      val prod = (row * col).toString
      val padding = " " * (4 - prod.length)
      padding + prod
    }
  }

  def makeRow(row:Int) = makeRowSeq(row).mkString

  def multiTable() = {
    val table = for (row <- 1 to 10) yield makeRow(row)
    println("table type:" + `type`(table))
    table.mkString("\n")
  }

  //可以查看变量类型。用``可使得成为scala identifier.type is reserved word
  def `type`[T: Manifest](t: T): Manifest[T] = manifest[T]
}

object Test {
  def main(args: Array[String]): Unit = {
    //val o = new ch07_multiplication_table
    //println(o.multiTable())
    //forTest()
    exceptionTest()
  }

  def matchTest(args: Array[String]): Unit = {
    val firstArg = if (!args.isEmpty) args(0) else ""
    val friend = firstArg match {
      case "salt" => "pepper"
      case "chips" => "salsa"
      case "egg" => "bacon"
      case _ => "huh?"
    }
  }

  def forTest(): Unit = {
    val files = (new File("./src/main/scala")).listFiles()
    for (f <- files) {
      //println(f)
    }
    println("only print .scala file:")
    for (f <- files if f.getName.endsWith(".scala")) {
      println(f)
    }
    grep(".*case class.*")

    def fileLines(file: File) = scala.io.Source.fromFile(file).getLines().toList
    def grep(pattern: String) = {
      for (
        file <- files
        if file.getName.endsWith(".scala"); //如果for用()，而这里的分号 必须要加
        line <- fileLines(file)
        if line.trim.matches(pattern)
      )println(file + ": " + line.trim)

      //()和{}有何区别???
      for {
        file <- files /*outer loop */
        if file.getName.endsWith(".scala")
        line <- fileLines(file) /*nested loop */
        trimmed = line.trim /*variable binding */
        if trimmed.matches(pattern)
      }println(file + ": " + trimmed)
    }

    def scalaFiles =
      for {
        file <- files
        if file.getName.endsWith(".scala")
      } yield file //yielded value will be included in s single collection,result collection type is
    //inferred. IN this case, it's Array[File]
  }

  def ifTest(args: Array[String]): Unit = {
    val filename =
      if (!args.isEmpty) args(0)
      else "default.txt"

  }

  def exceptionTest(): Unit = {
    val n = 10
    //the type of whole if expression is then the type of that branch which does compute something
    val half = if (n % 2 == 0) n/2 else throw new RuntimeException("n must be even")

    try {
      val f = new FileReader("input.txt")
    }catch {
      case ex: FileNotFoundException => println("not found")
      case ex: IOException =>
    }

    val file = new FileReader("build.sbt")
    try {
      //use the file
    }finally {
      file.close()
    }
    println(f,g)

    //不要在Finally语句中返回任何东西
    def f():Int = try { return 1 } finally { return 2}
    def g():Int = try { 1 } finally { 2}
  }
}
